home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d26 / asmtut4.arc / CHAP23.DOC < prev    next >
Text File  |  1990-08-10  |  28KB  |  657 lines

  1.  
  2.  
  3.  
  4.                                                                            253
  5.  
  6.                                  CHAPTER 23 - XLAT
  7.  
  8.  
  9.              The 800 pound gorilla in the computer field is, of course, IBM.
  10.              It can go its own way and other companies have to adjust to keep
  11.              themselves in line with what IBM is doing.
  12.  
  13.              You have been using ASCII characters since the first time you
  14.              used BASIC (or whatever your first high-level language was).
  15.              Every character has a unique number which represents it.
  16.  
  17.                    character    ASCII encoding
  18.  
  19.                       A              65d
  20.                       a              97d
  21.                       ?              63d
  22.                       0              48d
  23.  
  24.              IBM has its own encoding for mainframe computers. It is called
  25.              EBCDIC (pronounced ebb'-sih-dick).{1} It is a spinoff of the
  26.              coding on punch cards. You remember punch cards? This coding is
  27.              entirely different from ASCII. Here are some examples.
  28.  
  29.                    character    ASCII code      EBCDIC code
  30.  
  31.                       a               97d           129d
  32.                       ?               63d           111d                      
  33.                       0               48d           240d
  34.                       H               72d           200d
  35.                       I               73d           201d
  36.                       J               74d           209d
  37.                       K               75d           210d
  38.  
  39.              You can see that there is no relationship between the two
  40.              encodings. Also, notice that while the alphabet is a continuous
  41.              section of ASCII coding, there are breaks in the EBCDIC code
  42.              (I=201, J=209).
  43.  
  44.              All PCs use ASCII, so if we want to transfer text from a PC to an
  45.              IBM mainframe computer, we need to change  ASCII -> EBCDIC going
  46.              to the mainframe and change EBCDIC -> ASCII coming from the
  47.              mainframe. This is the responsibility of the communications
  48.              program that runs the modem, so you will never have to do it
  49.              yourself. Intel has provided an instruction to help the
  50.              communications program do this translation. It is called XLAT.
  51.  
  52.              In order to use XLAT, you need a translation table. This is a 256
  53.              byte array where each element of the array contains the result
  54.              you want. Looking at the data above:
  55.  
  56.              ____________________
  57.  
  58.                 1. Which stands for Extended Binary Coded Decimal Interchange
  59.              Code.
  60.  
  61.              ______________________
  62.  
  63.              The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
  64.  
  65.  
  66.  
  67.  
  68.              The PC Assembler Tutor                                        254
  69.              ______________________
  70.  
  71.  
  72.              CHARACTER   ASCII TO EBCDIC TABLE      EBCDIC TO ASCII TABLE
  73.  
  74.                  a         array1 [97] = 129          array2 [129] = 97
  75.                  ?         array1 [63] = 111          array2 [111] = 63
  76.                  0         array1 [48] = 240          array2 [240] = 48
  77.                  H         array1 [72] = 200          array2 [200] = 72
  78.                  I         array1 [73] = 201          array2 [201] = 73
  79.                  J         array1 [74] = 209          array2 [209] = 74
  80.                  K         array1 [75] = 210          array2 [210] = 75
  81.  
  82.              We have two different tables here. Array1 takes the ASCII
  83.              encoding and gives back the EBCDIC encoding. Array2 takes the
  84.              EBCDIC encoding and gives back the ASCII encoding. For each
  85.              character, the appropriate table gives the correct translation
  86.              from one encoding to another. All we need now is the translation
  87.              instruction. Put the address of the translation table in BX. This
  88.              table should be in the DS segment, but DS may be overriden:
  89.  
  90.                  mov  bx, offset ascii_to_ebcdic_table
  91.  
  92.              Put the character you want translated in al:
  93.  
  94.                  mov  al, character
  95.  
  96.              translate:
  97.  
  98.                  xlat
  99.  
  100.              To translate a 20 byte string of ASCII data into EBCDIC, you
  101.              might have the following code:
  102.  
  103.              ;----------
  104.                  mov  di, offset ebcdic_string
  105.                  mov  ax, seg ebcdic_string
  106.                  mov  es, ax
  107.  
  108.                  mov  si, offset ascii_string
  109.  
  110.                  mov  bx, offset ascii_to_ebcdic_table
  111.                  mov  cx, 20                   ; translate 20 bytes
  112.                  cld                           ; clear DF (increment)
  113.  
  114.              translation_loop:
  115.                  lodsb                         ; ascii to al
  116.                  xlat                          ; translate
  117.                  stosb                         ; al to ebcdic
  118.                  loop translation_loop
  119.              ; ----------
  120.  
  121.              Since this is ASCII to EBCDIC, if AL contained 63 before XLAT,
  122.              then after XLAT AL would contain 111. If AL contained 73 before
  123.              XLAT, then after XLAT it would contain 201. If AL contained 97
  124.              before XLAT, after XLAT it would contain 129.
  125.  
  126.              If we wanted to go the other direction we would have to make the
  127.              EBCDIC string the source string, make the ASCII string the
  128.  
  129.  
  130.  
  131.  
  132.              Chapter 23 - Xlat                                             255
  133.              _________________
  134.  
  135.              destination string, and use the other table:
  136.  
  137.                  mov  bx, offset ebcdic_to_ascii_table
  138.               
  139.              The rest of the code would be the same.
  140.  
  141.  
  142.              Since this is done by the communications program, we won't
  143.              concern ourselves with ASCII <-> EBCDIC any more, but we will use
  144.              XLAT in two slightly different ways.
  145.  
  146.  
  147.              First, let's categorize characters. Some things are Whitespace
  148.              (that is, tabs, newlines, spaces, form feeds, etc.) Some
  149.              characters are octal, decimal, punctuation, hex, etc. There is a
  150.              pre-existing table called translation_table in the subdirectory
  151.              XTRAFILE. Its pathname is \xtrafile\transtbl.obj. It has all 256
  152.              ascii characters coded in the following way:
  153.  
  154.                     WHITESPACE    EQU  80h     ; 1000 0000
  155.                     PUNCTUATION   EQU  40h     ; 0100 0000
  156.                     ALPHABETIC    EQU  20h     ; 0010 0000
  157.                     OCTAL         EQU  10h     ; 0001 0000
  158.                     DECIMAL       EQU  08h     ; 0000 1000
  159.                     HEX           EQU  04h     ; 0000 0100
  160.                     BOX_CHAR      EQU  02h     ; 0000 0010
  161.                     GREEK_CHAR    EQU  01h     ; 0000 0001
  162.  
  163.              If the character is whitespace, then the leftmost bit is set. If
  164.              it is a greek character (ascii 224 - 239 on the PC) then the
  165.              rightmost bit is set. If it is more than one thing, then the
  166.              appropriate bits are set. For instance, '6' is octal, decimal and
  167.              hex, so it's encoding is:
  168.  
  169.                  '6'  0001 1100
  170.  
  171.              'a' is both alphabetic and hex, so it's encoding is:
  172.  
  173.                  'a'  0010 0100
  174.  
  175.              The following program inputs a character, and finds out whether
  176.              it is punctuation, a letter, etc. If it is none of the eight
  177.              things, then the program prints that nothing was found. It is the
  178.              same block of code over and over, so you might want to do only
  179.              part, or you might want to cut it out with a word processor and
  180.              insert it in the template file (don't forget to delete the page
  181.              headers and page numbers).
  182.  
  183.  
  184.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  185.              EXTRN  translation_table:BYTE  ;\xtrafile\transtbl.obj
  186.               
  187.              whitespace_banner   db "It is whitespace." , 0 
  188.              punctuation_banner  db "It is punctuation." , 0 
  189.              alphabet_banner     db "It is alphabetic." , 0 
  190.              octal_banner        db "It is octal." , 0 
  191.              decimal_banner      db "It is decimal." , 0 
  192.  
  193.  
  194.  
  195.  
  196.              The PC Assembler Tutor                                        256
  197.              ______________________
  198.  
  199.              hex_banner          db "It is hex." , 0 
  200.              drawing_banner      db "It is a box drawing character." , 0 
  201.              greek_banner        db "It is a Greek character." , 0 
  202.              nothing_banner      db "No match was found." , 0 
  203.               
  204.              dirty_flag          db ? 
  205.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  206.  
  207.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  208.                     WHITESPACE    EQU  80h 
  209.                     PUNCTUATION   EQU  40h 
  210.                     ALPHABETIC    EQU  20h 
  211.                     OCTAL         EQU  10h 
  212.                     DECIMAL       EQU  08h
  213.                     HEX           EQU  04h 
  214.                     BOX_CHAR      EQU  02h 
  215.                     GREEK_CHAR    EQU  01h 
  216.               
  217.                     ; set up the xlat table 
  218.                     mov   ax, seg translation_table 
  219.                     mov   es, ax 
  220.                     mov   bx, offset translation_table 
  221.               
  222.              outer_loop: 
  223.                     mov   dirty_flag, 0       ; marker for success 
  224.                     call get_ascii_byte       ; input a byte to al 
  225.                     xlat es:[bx]              ; do the translation 
  226.               
  227.                     test  al, WHITESPACE 
  228.                     jz    punct_check 
  229.                     push  ax                  ; save translation in al 
  230.                     mov   ax, offset whitespace_banner 
  231.                     call  print_string 
  232.                     pop   ax 
  233.                     mov   dirty_flag, 1       ; set the dirty flag 
  234.               
  235.              punct_check: 
  236.                     test  al, PUNCTUATION 
  237.                     jz    alpha_check 
  238.                     push  ax                  ; save translation in al 
  239.                     mov   ax, offset punctuation_banner 
  240.                     call  print_string 
  241.                     pop   ax 
  242.                     mov   dirty_flag, 1       ; set the dirty flag 
  243.               
  244.              alpha_check: 
  245.                     test  al, ALPHABETIC 
  246.                     jz    octal_check 
  247.                     push  ax                  ; save translation in al 
  248.                     mov   ax, offset alphabet_banner 
  249.                     call  print_string 
  250.                     pop   ax 
  251.                     mov   dirty_flag, 1       ; set the dirty flag 
  252.               
  253.              octal_check: 
  254.                     test  al, OCTAL 
  255.                     jz    decimal_check 
  256.  
  257.  
  258.  
  259.  
  260.              Chapter 23 - Xlat                                             257
  261.              _________________
  262.  
  263.                     push  ax                  ; save translation in al 
  264.                     mov   ax, offset octal_banner 
  265.                     call  print_string 
  266.                     pop   ax 
  267.                     mov   dirty_flag, 1       ; set the dirty flag 
  268.               
  269.              decimal_check: 
  270.                     test  al, DECIMAL 
  271.                     jz    hex_check 
  272.                     push  ax                  ; save translation in al 
  273.                     mov   ax, offset decimal_banner 
  274.                     call  print_string 
  275.                     pop   ax 
  276.                     mov   dirty_flag, 1       ; set the dirty flag 
  277.               
  278.              hex_check: 
  279.                     test  al, HEX 
  280.                     jz    drawing_check 
  281.                     push  ax                  ; save translation in al 
  282.                     mov   ax, offset hex_banner 
  283.                     call  print_string 
  284.                     pop   ax 
  285.                     mov   dirty_flag, 1       ; set the dirty flag 
  286.               
  287.              drawing_check: 
  288.                     test  al, BOX_CHAR 
  289.                     jz    greek_check 
  290.                     push  ax                  ; save translation in al 
  291.                     mov   ax, offset drawing_banner 
  292.                     call  print_string 
  293.                     pop   ax 
  294.                     mov   dirty_flag, 1       ; set the dirty flag 
  295.               
  296.              greek_check: 
  297.                     test  al, GREEK_CHAR 
  298.                     jz    nothing_check 
  299.                     push  ax                  ; save translation in al 
  300.                     mov   ax, offset greek_banner 
  301.                     call  print_string 
  302.                     pop   ax 
  303.                     mov   dirty_flag, 1       ; set the dirty flag 
  304.               
  305.              nothing_check: 
  306.                     cmp   dirty_flag, 0       ; was anything found? 
  307.                     je    print_nothing_banner 
  308.                     jmp   outer_loop 
  309.              print_nothing_banner: 
  310.                     mov   ax, offset nothing_banner 
  311.                     call  print_string 
  312.                     jmp   outer_loop 
  313.               
  314.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  315.  
  316.              you need to:
  317.  
  318.                  link prog1+transtbl+\asmhelp ;
  319.  
  320.  
  321.  
  322.  
  323.  
  324.              The PC Assembler Tutor                                        258
  325.              ______________________
  326.  
  327.              The program is long, but straightforward. Input a character and
  328.              get its encoding. Test for each characteristic. If it is found,
  329.              print the appropriate message and set the dirty_flag to indicate
  330.              something was printed. At the end, if nothing was printed, print
  331.              the failure message. 
  332.  
  333.              Notice that the translation table is in ES and we are using a
  334.              segment override for it. If you look at the EXTRN statement for
  335.              'translation_table', you will see that even though we are using
  336.              ES, it is declared EXTRN in a segment with an:
  337.  
  338.                  ASSUME ds:DATASTUFF
  339.  
  340.              statement. How can we get away with this? The assembler never
  341.              deals with 'translation table' directly. The only thing it does
  342.              is put the offset in BX. We put the segment override in ourselves
  343.              with:
  344.  
  345.                  xlat es:[bx] 
  346.  
  347.              so the assembler never has to decide whether a segment override
  348.              is necessary or which segment override to use.
  349.  
  350.  
  351.              WORD SEARCH
  352.  
  353.              When doing the mock word search program in the chapter on string
  354.              instructions, I mentioned that it really wouldn't cut the mustard
  355.              when it comes to real word searches. Why?  If we are looking for
  356.              "when" we also want to find "When". If we are looking for 
  357.              " searches ", we also want to find " searches,", that is,
  358.              punctuation should not interefere unless we want it to, and
  359.              capitals should not interefere unless we want them to. With the
  360.              aid of a translation table, we will make a word search program
  361.              which uses the following rules. In the SEARCH string (the string
  362.              that defines what you are looking for):
  363.  
  364.                  (1) Any small letter will match either a small or large      
  365.                      letter.
  366.                  (2) A capital letter will match only a capital letter.
  367.                  (3) A blank will match any whitespace or punctuation.
  368.                  (4) A punctuation mark will only match itself.
  369.  
  370.              With these rules "Why" must start with a capital 'W' to be a
  371.              match, but 'h' and 'y' may be either capital or small. " some,"
  372.              may have any whitespace (including a carriage return) in front,
  373.              but must hava a comma ',' at the end. 
  374.  
  375.              This program has two data files. \XTRAFILE\SRCHTBL.OBJ contains
  376.              the translation table. It is called "wordsearch_table" and is in
  377.              DATASTUFF, so will be in our normal DS segment. In order to have
  378.              text to search I have included an object file that is the text of
  379.              a chapter from a book. (The object file text includes carriage
  380.              returns). The text is a C string - it is terminated by a 0.
  381.  
  382.              The book was written by C.D. Huffam, and is the autobiographical
  383.              account of his dual life as a writer and lecturer. The book is
  384.  
  385.  
  386.  
  387.  
  388.              Chapter 23 - Xlat                                             259
  389.              _________________
  390.  
  391.              called "A Tale of Two C.D.s". The object file with the text is
  392.              \XTRAFILE\TWOTALE.OBJ. It is in a private segment and will use ES
  393.              as a segment register. There is also a straight text file which
  394.              you can print out so you can see what is in the object file. It
  395.              is \XTRAFILE\TWOTALE.DOC.
  396.  
  397.              Here's the program. The explaination is at the end.
  398.  
  399.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  400.              EXTRN  tale_text:BYTE, wordsearch_table:BYTE 
  401.               
  402.              entry_message    db   13,10, "Enter a word for a word search", 0
  403.              no_match_message db   "There was no match", 0 
  404.              input_buffer     db   80 dup (?)  
  405.              text_file_length dw   ? 
  406.              letter_count     dw   ? 
  407.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  408.  
  409.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  410.               
  411.                     ; find the length of the text file 
  412.                     mov   ax, seg tale_text      ; load es register 
  413.                     mov   es, ax                              
  414.               
  415.                     mov   di, offset tale_text   ; offset to di 
  416.                     mov   bx, di                 ; copy to bx 
  417.                     mov   al, 0                  ; try to match zero 
  418.                     cld                          ; clear DF (increment) 
  419.               
  420.              string_end_loop: 
  421.                     scasb                        ; search for zero 
  422.                     jne   string_end_loop 
  423.               
  424.                     dec   di                  ; one too many , so decrement 
  425.                     sub   di, bx                   ; finish - start = length 
  426.                     mov   text_file_length, di     ; length of text_file 
  427.               
  428.               
  429.              big_loop: 
  430.                     ; get a word for the word search 
  431.                     mov   ax, offset entry_message
  432.                     call  print_string 
  433.                     mov   ax, offset input_buffer 
  434.                     call  get_string 
  435.               
  436.                     ; find the end of string 
  437.                     mov   al, 0               ; compare with 0 
  438.                     mov   bx, offset input_buffer 
  439.                     mov   cx, 0               ; letter count 
  440.              letter_count_loop: 
  441.                     cmp   al, [bx]            ; compare to 0 
  442.                     je    end_of_count_loop 
  443.                     inc   cx                  ; increment count 
  444.                     inc   bx                  ; increment pointer 
  445.                     jmp   letter_count_loop 
  446.              end_of_count_loop: 
  447.                     cmp   cx, 0               ; if 0, string is empty 
  448.  
  449.  
  450.  
  451.  
  452.              The PC Assembler Tutor                                        260
  453.              ______________________
  454.  
  455.                     je    big_loop            ; so start again 
  456.                     mov   letter_count, cx 
  457.               
  458.                     ; look for word match. In this program, the text string 
  459.                     ; is referenced by si and the search string is referenced
  460.                     ; by di.
  461.               
  462.                     mov   si, offset tale_text 
  463.                     mov   cx, text_file_length    ; length of file
  464.                     sub   cx, letter_count        ; last possible match
  465.                     inc   cx                      ; +1 for boundary condition
  466.               
  467.                     ; set up translation table ( it is in DATASTUFF ) 
  468.                     mov   bx, offset wordsearch_table 
  469.               
  470.               
  471.              word_search_loop: 
  472.                     push  si                  ; save a copy 
  473.                     push  cx                  ; save a copy 
  474.                     mov   di, offset input_buffer 
  475.                     mov   cx, letter_count 
  476.               
  477.               
  478.              letter_loop: 
  479.                     mov   al, es:[si]         ; text to al 
  480.                     cmp   al, [di]            ; same as search string? 
  481.                     je    next_letter 
  482.                     xlat                      ; if not, translate 
  483.                     cmp   al, [di]            ; allowable substitute? 
  484.                     jne   new_start           ; if not, start at new place 
  485.              next_letter: 
  486.                     inc   di                  ; move to next letter 
  487.                     inc   si
  488.                     loop  letter_loop
  489.               
  490.                     ; we fell through, so we found a complete match 
  491.                     jmp    found_it 
  492.               
  493.                     ; no match. are we finished? 
  494.              new_start: 
  495.                     pop   cx 
  496.                     pop   si 
  497.                     inc   si                  ; move to next character 
  498.                     loop  word_search_loop 
  499.               
  500.                     ; we fell through. finished, but no match 
  501.                     mov   ax, offset no_match_message
  502.                     call  print_string 
  503.                     jmp   big_loop 
  504.               
  505.              found_it: 
  506.                     pop   cx                  ; take cx off the stack 
  507.                     pop   si                  ; start of the match 
  508.               
  509.                     ; move 25 characters to buffer for printing 
  510.                     mov   di, offset input_buffer 
  511.                     mov   cx, 25 
  512.  
  513.  
  514.  
  515.  
  516.              Chapter 23 - Xlat                                             261
  517.              _________________
  518.  
  519.              character_move: 
  520.                     mov   al, es:[si] 
  521.                     mov   [di], al 
  522.                     inc   si                  ; increment pointers 
  523.                     inc   di 
  524.                     loop  character_move 
  525.               
  526.                     mov   BYTE PTR [di], 0    ; end of string 
  527.                     mov   ax, offset input_buffer 
  528.                     call  print_string 
  529.                     jmp   big_loop 
  530.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  531.  
  532.              You need to:
  533.  
  534.                  link prog2+twotale+srchtbl+\asmhelp ;
  535.  
  536.              to get asmhelp and the two data files in the program.
  537.  
  538.              This program is very similar to the search program in the chapter
  539.              on strings. However, because of where the files are, the pointers
  540.              have been changed around. Therefore, it is safer if you simply
  541.              cut out the program with a word processor and paste it into the
  542.              template file rather than try to modify the prevoius search
  543.              program.{2}
  544.  
  545.              It is assumed that you did the string match program. The logic is
  546.              the same and will not be covered again. First we input a search
  547.              string. Then starting at the beginning of the text to be search
  548.              we check till we find the first match. If we find a match, we
  549.              print out 25 characters starting with the first character of the
  550.              match. If no match is found, a message to that effect is printed.
  551.  
  552.              The character match is a two step process. The character from the
  553.              text is put in AL. It is compared with the search character for
  554.              an EXACT match. If they match, we are done. If not, we use XLAT
  555.              on AL (the character from the text) which will translate to its
  556.              allowable substitute. In fact, all this is just: (1) all capital
  557.              letters become small, (2) all punctuation becomes spaces, and (3)
  558.              all whitespace becomes spaces. Once again, we compare AL with the
  559.              search character. If we have a match, ok. If not, we start over.
  560.  
  561.              The text is in ES, the translation table is in DS, so it is
  562.              inconvenient to use the string instructions in this program.
  563.  
  564.              Try to match a word at the beginning of the line, end of the
  565.              line, with and without punctuation and with and without capitals.
  566.              If you go across a line break, you need to substitute two blanks
  567.              in the search string for CRLF (13,10).
  568.  
  569.  
  570.              ____________________
  571.  
  572.                 2. You should understand what is going on in the code before
  573.              you run these programs. I didn't write the code for myself, I
  574.              wrote it for you. If you run it but don't understand it, it won't
  575.              help you a bit.
  576.  
  577.  
  578.  
  579.  
  580.              The PC Assembler Tutor                                        262
  581.              ______________________
  582.  
  583.              Suppose you are not interested in all 256 values of the
  584.              translation table. Let's say that you only want to have a
  585.              translation table for the numbers from 0 to 99. Can you still use
  586.              this? Yes, but you need to put in some range checking to make
  587.              sure that you have valid data.
  588.  
  589.                  MAX_VALUE EQU 99
  590.  
  591.                  mov  al, data_byte       ; byte to al
  592.                  cmp  al, MAX_VALUE       ; too large?
  593.                  ja   data_error          ; report error
  594.                  xlat
  595.  
  596.              This insures that any data that is out of range is not
  597.              translated. Therefore the translation table only needs to be 100
  598.              bytes long (0 - 99). 
  599.  
  600.              If you want more than 256 elements in the translation table you
  601.              need to use words, not bytes, and you cannot use XLAT. You can
  602.              make your own code to do the same thing.
  603.  
  604.                  MAX_VALUE EQU 999
  605.                  my_translation_table     dw   1000 dup (?)
  606.  
  607.              if you put the translation data into the table, you can then have
  608.              the following code:
  609.  
  610.                  mov  bx, offset my_translation_table
  611.  
  612.                  ; - - - - - translation block
  613.                  mov  si, data_word       ; word to si
  614.                  cmp  si, MAX_VALUE       ; too large?
  615.                  ja   data_error
  616.                  shl  si, 1         ; SI x 2 = number of BYTES into table
  617.                  mov  ax, [bx+si]         ; base + offset
  618.                  ; - - - - - end of translation block
  619.  
  620.              XLAT is about twice as fast as this last code, so when you have a
  621.              choice always use XLAT.
  622.  
  623.  
  624.  
  625.  
  626.  
  627.  
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.              Chapter 23 - Xlat                                             263
  645.              _________________
  646.  
  647.                                           SUMMARY
  648.  
  649.  
  650.              XLAT 
  651.  
  652.                  BX holds the address of a 256 byte array called a
  653.                  translation table. AL holds the character to be translated.
  654.                  If x is the value in AL before XLAT, then after XLAT,
  655.                  AL=array[x].
  656.  
  657.